package com.googlecode.jtoy.productorandconsumer;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 在JDK5.0以后，JAVA提供了新的更加健壮的线程处理机制，包括了同步、锁定、线程池等等，它们可以实现更小粒度上的控制。
 * await()和signal()就是其中用来做同步的两种方法，它们的功能基本上和wait()/notify()相同，
 * 完全可以取代它们，但是它们和新引入的锁定机制Lock直接挂钩，具有更大的灵活性。
 * 
 * @author shangxj
 * @date 4:25:20 PM, Aug 31, 2011
 */
public class AwaitAndSignal {

	private LinkedList<String> myList = new LinkedList<String>();
	private int MAX = 100;
	private int i = 0;

	private final Lock lock = new ReentrantLock();
	private final Condition full = lock.newCondition();
	private final Condition empty = lock.newCondition();

	public static void main(String[] args) {
		new AwaitAndSignal().start();
	}

	public void start() {
		new Productor().start();
		new Consumer().start();
		new Consumer().start();
	}

	class Productor extends Thread {

		public void run() {
			while (true) {

				try {
					Thread.sleep((long) (100 * Math.random()));
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}

				lock.lock();
				try {
					while (myList.size() == MAX) {
						System.out.println("warning: it's full!");
						full.await();
					}
					String product = String.valueOf(++i);
					if (myList.add(product)) {
						System.out.println("Productor: ++++++++++++++++++++" + product);
						empty.signal();
					}
				} catch (InterruptedException e) {
					System.out.println("productor is interrupted!");
				} finally {
					lock.unlock();
				}
			}
		}
	}

	class Consumer extends Thread {

		public void run() {
			while (true) {
				try {
					Thread.sleep((long) (200 * Math.random()));
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}

				lock.lock();
				try {
					while (myList.size() == 0) {
						System.out.println("warning: it's empty!");
						empty.await();
					}
					String product = myList.removeFirst();
					System.out.println("Consumer: --------------------" + product);
					full.signal();
				} catch (InterruptedException e) {
					System.out.println("consumer is interrupted!");
				} finally {
					lock.unlock();
				}
			}
		}
	}

}